#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
报告生成器模块
负责生成分析结果报告
"""

import os
import json
from datetime import datetime
from pathlib import Path
from typing import Dict, Any, List, Optional

from src.utils.logger import get_logger
from src.models.result import AnalysisResult

class ReportGenerator:
    """报告生成器类"""
    
    def __init__(
        self,
        result: AnalysisResult,
        output_path: Path,
        config: Optional[Dict[str, Any]] = None
    ):
        """
        初始化报告生成器
        
        Args:
            result: 分析结果对象
            output_path: 输出路径
            config: 配置信息
        """
        self.result = result
        self.output_path = Path(output_path)
        self.config = config or {}
        self.logger = get_logger("ReportGenerator")
        
        # 设置报告格式，确保默认至少包含HTML和JSON
        self.formats = self.config.get("formats", ["html", "json"])
        if "html" not in self.formats:
            self.formats.append("html")
        
        # 确保输出目录存在
        os.makedirs(self.output_path, exist_ok=True)
        
        self.logger.info(f"初始化报告生成器，输出路径: {self.output_path}")
    
    def generate(self) -> List[Path]:
        """
        生成报告
        
        Returns:
            生成的报告文件路径列表
        """
        reports = []
        
        # 创建时间戳作为文件名一部分
        timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
        app_name = self.result.app_name or "unknown"
        base_filename = f"{app_name}_{self.result.platform}_{timestamp}"
        
        html_report_path = None
        
        # 根据配置的格式生成不同类型的报告
        for fmt in self.formats:
            if fmt == "json":
                report_path = self._generate_json_report(base_filename)
                reports.append(report_path)
            elif fmt == "html":
                report_path = self._generate_html_report(base_filename)
                html_report_path = report_path
                reports.append(report_path)
            elif fmt == "pdf":
                # PDF生成可能需要额外依赖
                try:
                    report_path = self._generate_pdf_report(base_filename)
                    reports.append(report_path)
                except Exception as e:
                    self.logger.warning(f"生成PDF报告失败: {e}")
        
        # 创建index.html指向HTML报告
        if html_report_path:
            index_path = self.output_path / "index.html"
            rel_path = html_report_path.name
            
            # 创建简单的重定向
            index_content = f"""<!DOCTYPE html>
<html>
<head>
    <meta http-equiv="refresh" content="0;url={rel_path}">
    <title>应用框架分析报告</title>
</head>
<body>
    <p>如果您的浏览器没有自动跳转，请<a href="{rel_path}">点击这里</a>访问报告。</p>
</body>
</html>
"""
            with open(index_path, 'w', encoding='utf-8') as f:
                f.write(index_content)
                
            reports.append(index_path)
            self.logger.info(f"已创建索引文件: {index_path}")
        
        self.logger.info(f"报告生成完成，共 {len(reports)} 个文件")
        return reports
    
    def _generate_json_report(self, base_filename: str) -> Path:
        """
        生成JSON格式报告
        
        Args:
            base_filename: 基础文件名
            
        Returns:
            报告文件路径
        """
        report_path = self.output_path / f"{base_filename}.json"
        
        # 转换结果为JSON
        data = self.result.to_dict()
        
        with open(report_path, 'w', encoding='utf-8') as f:
            json.dump(data, f, ensure_ascii=False, indent=2)
        
        self.logger.info(f"JSON报告已保存: {report_path}")
        return report_path
    
    def _generate_html_report(self, base_filename: str) -> Path:
        """
        生成HTML格式报告
        
        Args:
            base_filename: 基础文件名
            
        Returns:
            报告文件路径
        """
        report_path = self.output_path / f"{base_filename}.html"
        
        try:
            from jinja2 import Environment, FileSystemLoader, select_autoescape
            
            # 获取模板目录
            template_dir = self.config.get("template_dir", "./templates")
            
            # 确保CSS文件被复制到输出目录
            css_source = Path(template_dir) / "style.css"
            css_dest = self.output_path / "style.css"
            
            if css_source.exists():
                import shutil
                shutil.copy(css_source, css_dest)
                css_path = "style.css"  # 相对路径，将在同一目录
            else:
                # 如果CSS文件不存在，使用绝对路径
                css_path = str(css_source)
            
            # 创建Jinja2环境
            env = Environment(
                loader=FileSystemLoader(template_dir),
                autoescape=select_autoescape(['html', 'xml'])
            )
            
            # 加载模板
            template = env.get_template("report.html")
            
            # 渲染HTML
            html_content = template.render(
                result=self.result,
                generated_time=datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
                title=f"应用框架分析报告 - {self.result.app_name}",
                css_path=css_path
            )
            
            # 保存HTML文件
            with open(report_path, 'w', encoding='utf-8') as f:
                f.write(html_content)
            
            self.logger.info(f"HTML报告已保存: {report_path}")
        except Exception as e:
            self.logger.warning(f"生成HTML报告失败: {e}")
            
            # 生成一个简单的HTML报告作为后备
            self._generate_simple_html_report(report_path)
        
        return report_path
    
    def _generate_simple_html_report(self, report_path: Path) -> None:
        """
        生成简单的HTML报告（不依赖模板）
        
        Args:
            report_path: 报告文件路径
        """
        # 创建简单的CSS文件
        css_path = self.output_path / "simple_style.css"
        simple_css = """
        body { font-family: Arial, sans-serif; margin: 0; padding: 20px; color: #333; }
        h1, h2, h3, h4 { color: #2c3e50; }
        .header { background-color: #f8f9fa; padding: 20px; border-radius: 5px; margin-bottom: 20px; }
        .framework { background-color: #f8f9fa; padding: 15px; margin-bottom: 15px; border-radius: 5px; }
        .confidence { background-color: #e9ecef; height: 20px; width: 100%; margin: 10px 0; }
        .confidence-bar { background-color: #4caf50; height: 100%; text-align: right; color: white; padding-right: 5px; }
        ul { padding-left: 20px; }
        .main-framework { border-left: 4px solid #4a89dc; background-color: #f0f7ff; }
        .related-frameworks { display: flex; flex-wrap: wrap; gap: 10px; padding: 0; }
        .related-frameworks li { background-color: #e9f2fd; padding: 5px 10px; border-radius: 15px; font-size: 0.9em; display: inline-block; margin-right: 5px; }
        .category-section { margin-top: 20px; border-top: 1px solid #ddd; padding-top: 15px; }
        """
        
        with open(css_path, 'w', encoding='utf-8') as f:
            f.write(simple_css)
        
        # 分析框架关系
        self.result.analyze_framework_relationships()
        
        # 获取主要框架和按类别分组的框架
        main_frameworks = self.result.get_main_frameworks()
        frameworks_by_category = self.result.get_frameworks_by_category()
        
        # 生成主要框架HTML
        main_frameworks_html = ""
        if main_frameworks:
            for fw in main_frameworks:
                confidence_percent = int(fw.confidence * 100)
                related_html = ""
                if fw.related_frameworks:
                    related_html = """
                    <h4>相关框架:</h4>
                    <ul class="related-frameworks">
                        {related_items}
                    </ul>
                    """.format(
                        related_items="".join(f"<li>{related}</li>" for related in fw.related_frameworks)
                    )
                
                main_frameworks_html += f"""
                <div class="framework main-framework">
                    <h3>{fw.name} {fw.version or ""}</h3>
                    <p><strong>类别:</strong> {fw.category}</p>
                    <div class="confidence">
                        <div class="confidence-bar" style="width: {confidence_percent}%;"> 
                          {confidence_percent}%
                        </div>
                    </div>
                    <h4>特征:</h4>
                    <ul>
                        {"".join(f"<li>{feature}</li>" for feature in fw.features)}
                    </ul>
                    {related_html}
                </div>
                """
        
        # 生成按类别分组的框架HTML
        frameworks_by_category_html = ""
        if len(frameworks_by_category) > 1:
            for category, frameworks in frameworks_by_category.items():
                category_frameworks_html = ""
                for fw in frameworks:
                    confidence_percent = int(fw.confidence * 100)
                    related_html = ""
                    if fw.related_frameworks:
                        related_html = """
                        <h4>相关框架:</h4>
                        <ul class="related-frameworks">
                            {related_items}
                        </ul>
                        """.format(
                            related_items="".join(f"<li>{related}</li>" for related in fw.related_frameworks)
                        )
                    
                    category_frameworks_html += f"""
                    <div class="framework">
                        <h3>{fw.name} {fw.version or ""}</h3>
                        <div class="confidence">
                            <div class="confidence-bar" style="width: {confidence_percent}%;"> 
                              {confidence_percent}%
                            </div>
                        </div>
                        <h4>特征:</h4>
                        <ul>
                            {"".join(f"<li>{feature}</li>" for feature in fw.features)}
                        </ul>
                        {related_html}
                    </div>
                    """
                
                frameworks_by_category_html += f"""
                <div class="category-section">
                    <h3>{category}</h3>
                    {category_frameworks_html}
                </div>
                """
        else:
            # 如果没有多个类别，直接生成所有框架
            for fw in self.result.frameworks:
                confidence_percent = int(fw.confidence * 100)
                related_html = ""
                if fw.related_frameworks:
                    related_html = """
                    <h4>相关框架:</h4>
                    <ul class="related-frameworks">
                        {related_items}
                    </ul>
                    """.format(
                        related_items="".join(f"<li>{related}</li>" for related in fw.related_frameworks)
                    )
                
                frameworks_by_category_html += f"""
                <div class="framework">
                    <h3>{fw.name} {fw.version or ""}</h3>
                    <p><strong>类别:</strong> {fw.category}</p>
                    <div class="confidence">
                        <div class="confidence-bar" style="width: {confidence_percent}%;"> 
                          {confidence_percent}%
                        </div>
                    </div>
                    <h4>特征:</h4>
                    <ul>
                        {"".join(f"<li>{feature}</li>" for feature in fw.features)}
                    </ul>
                    {related_html}
                </div>
                """
        
        # 生成完整HTML
        html_content = f"""
        <!DOCTYPE html>
        <html>
        <head>
            <meta charset="UTF-8">
            <title>应用框架分析报告 - {self.result.app_name}</title>
            <link rel="stylesheet" href="simple_style.css">
        </head>
        <body>
            <div class="header">
                <h1>应用框架分析报告</h1>
                <p><strong>应用名称:</strong> {self.result.app_name or "未知"}</p>
                <p><strong>应用版本:</strong> {self.result.app_version or "未知"}</p>
                <p><strong>平台:</strong> {self.result.platform}</p>
                <p><strong>分析时间:</strong> {self.result.analysis_time.strftime("%Y-%m-%d %H:%M:%S")}</p>
            </div>
            
            {main_frameworks_html if main_frameworks else ""}
            
            <h2>识别到的所有框架</h2>
            {frameworks_by_category_html if self.result.frameworks else "<p>未识别到任何框架</p>"}
            
            <div class="footer">
                <p>生成时间: {datetime.now().strftime("%Y-%m-%d %H:%M:%S")}</p>
                <p>应用程序框架分析器</p>
            </div>
        </body>
        </html>
        """
        
        with open(report_path, 'w', encoding='utf-8') as f:
            f.write(html_content)
        
        self.logger.info(f"简单HTML报告已保存: {report_path}")
    
    def _generate_pdf_report(self, base_filename: str) -> Path:
        """
        生成PDF格式报告
        
        Args:
            base_filename: 基础文件名
            
        Returns:
            报告文件路径
        """
        # 首先生成HTML报告
        html_path = self._generate_html_report(base_filename)
        pdf_path = self.output_path / f"{base_filename}.pdf"
        
        try:
            # 尝试使用weasyprint转换HTML为PDF
            from weasyprint import HTML
            HTML(html_path).write_pdf(pdf_path)
            
            self.logger.info(f"PDF报告已保存: {pdf_path}")
        except ImportError:
            # 如果没有weasyprint，尝试使用其他方法
            try:
                import pdfkit
                pdfkit.from_file(str(html_path), str(pdf_path))
                self.logger.info(f"PDF报告已保存: {pdf_path}")
            except ImportError:
                self.logger.warning("无法生成PDF报告：缺少pdfkit或weasyprint")
                raise
        
        return pdf_path 
